package io.simple.netty;

import injections.annotations.Property;
import io.simple.core.SSLContextFactory;
import io.simple.core.chain.Pipeline;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.ssl.SslHandler;
import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLEngine;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
 * Created with IntelliJ IDEA.
 * User: rehak
 * Date: 8/20/13
 * Time: 3:30 PM
 * To change this template use File | Settings | File Templates.
 */
public class HTTPSTransport extends HTTPTransport {

    private static final Logger LOGGER = LoggerFactory.getLogger(HTTPSTransport.class);
    @Property
    private SSLContextFactory sslContextFactory;

    public HTTPSTransport() {
        super();
    }

    public HTTPSTransport(int[] ports, String host, boolean keepAlive, int maxRequestInitialLineLength, int maxRequestHeaderSize, int maxRequestChunkSize, int maxContentLength, long timerTickDurationMillis, int timerTicksPerWheel, long readTimeOutMillis, SSLContextFactory sslContextFactory, Collection<Pipeline> pipelines) {
        super(ports, host, keepAlive, maxRequestInitialLineLength, maxRequestHeaderSize, maxRequestChunkSize, maxContentLength, timerTickDurationMillis, timerTicksPerWheel, readTimeOutMillis, pipelines);
        this.sslContextFactory = sslContextFactory;
    }

    @Override
    public ChannelPipelineFactory getPipelineFactory() {
        return new ChannelPipelineFactory() {
            @Override
            public ChannelPipeline getPipeline() {
                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("Timeout", new ReadTimeoutHandler(timer, readTimeOutMillis, TimeUnit.MILLISECONDS) {
                    @Override
                    protected void readTimedOut(ChannelHandlerContext ctx) throws Exception {
                        LOGGER.error("Timeout for " + ctx.getChannel().getRemoteAddress());
                        ctx.getChannel().close();
                    }
                });
                SSLEngine engine = null;
                try {
                    engine = sslContextFactory.getInstance().createSSLEngine();
                } catch (Exception ex) {
                    LOGGER.error("error starting SSL", new RuntimeException("Error initializing SSL engine", ex));
                    System.exit(-443);
                }
                engine.setUseClientMode(false);
                pipeline.addLast("ssl", new SslHandler(engine));
                pipeline.addLast("HttpRequestDecoder", new HttpRequestDecoder(maxRequestInitialLineLength, maxRequestHeaderSize, maxRequestChunkSize));
                pipeline.addLast("HttpChunkAggregator", new HttpChunkAggregator(maxContentLength));
                pipeline.addLast("HttpResponseEncoder", new HttpResponseEncoder());
//                pipeline.addLast("HttpDeflater", new HttpContentCompressor(2));
                pipeline.addLast("DefaultPipeline", getRoutingHandler());
                return pipeline;
            }
        };
    }

}
